/*
 * RLE.cpp
 *
 *  Created on: Jun 11, 2012
 *      Author: Nico
 */

#ifndef RLE_H_
#define RLE_H_

#include "includes.h"
#include "compressedStream.cpp"
#include "RLE.h"

/* Metodos publicos */

/* public */ void RLE::setInputFilename(const char* filename){
	this->inputFilename = (char*)filename;
}

/* public */ void RLE::setOutputFilename(const char* filename){
	this->outputFilename = (char*)filename;
}



RLECompress::RLECompress(){
	this->readingFromFile = false;
	this->debug = false;
}

RLECompress::RLECompress(const char* inputFilename , const int blockSize){
	this->debug = false;
	
	this->readingFromFile = true;
	
	this->imAtFirstBlock = true;
	
	this->lastReadSize = 0;
	this->blockSize = blockSize;
	
	this->setInputFilename(inputFilename);
	this->setOutputFilename("RLE.output.txt");
	
	this->last_1 = 1;
	this->last_2 = 2;
	this->last_3 = 3;
}



RLECompress::~RLECompress(){
	
	if( this->inputFile.is_open() ){
		this->inputFile.close();
	}
	
	if( this->readingFromFile == true ){
		delete this->outputFile;
	}
	/*
	if( this->outputFile.is_open() ){
		this->outputFile.close();
	}
	*/
}


/* protected */ int RLECompress::getNextBlockOfText(char** text){
	if( !this->inputFile.is_open() ){
		this->inputFile.open( this->inputFilename , ios::binary );
		if( !this->inputFile.is_open() ) return ERROR_FILE_NOT_EXIST;
		this->readingFromFile = true;
	}

	if( this->inputFile.eof() ){
		//cout << "Error de lectura." << endl;
		return ERROR_EOF;
	}

	this->inputFile.read( *text , this->blockSize );

	
	
	this->lastReadSize =  this->inputFile.gcount();
	if(debug) printf( "inputFile.gcount(): %d\n" , this->inputFile.gcount() );
	if(debug) printf( "strlen(text): %d\n" , strlen(*text) );
	if( this->lastReadSize == this->blockSize ){
		// Fix para ignorar caracter \0 al final del bloque
		if(debug) var_dump_string( *text , this->blockSize );
		if( last_char_is_null( *text , this->blockSize ) ){
			this->lastReadSize--;
			if(debug) printf("Ultimo char era NULL, lo ignoro.\n");
		}
	}else if( this->lastReadSize < this->blockSize ){
		// Fix para ignorar caracter \0 al final del bloque
		if(debug) printf( "this->lastReadSize < this->blockSize (%d < %d) entonces this->lastReadSize: %d\n" , this->lastReadSize , this->blockSize , this->lastReadSize-1 );
		this->lastReadSize--;
	}

	if( this->inputFile.bad() ){
		//cout << "Error de lectura." << endl;
		return ERROR_LECTURA;
	}
	
	return 0;
}



/* public */ int RLECompress::runNextBlock( string* compressed ){
	if( this->imAtFirstBlock == true ){
		this->imAtFirstBlock = false;
		this->outputFile = new OCompressedStream( this->outputFilename , this->blockSize );
	}
	uInt status;
	char* texto = (char*)malloc( this->blockSize * sizeof(char) );

	status = this->getNextBlockOfText(&texto);

	if( status == ERROR_LECTURA ){
		//cout << "Error de lectura." << endl;
		free(texto);
		return ERROR_LECTURA;

	}else if( status == ERROR_EOF ){
		//cout << "End of file." << endl;
		free(texto);
		return ERROR_EOF;
	}

	// Debug
	if(this->debug){
		printf( "Texto leido: '%s'\n" , texto );
		printf("BlockSize: %d\n",this->blockSize);
	}
	
	
	runBlock( texto , this->lastReadSize , compressed );
	
	//cout << "Escribiendo archivo " << this->outputFilename << endl;
	this->outputFile->writeRLEresult( compressed );
	
	free(texto);
	
	return 0;
}

/* public */ int RLECompress::runBlock( const char* texto , const uInt blockLength , string* compressed ){
	short int c;
	char* iterador = (char*)texto;
	short int count;
	compressed->clear();
	uInt i=0;
	while( iterador < (texto+blockLength) ){
		c = *iterador;
		*compressed += c;
		
        if( ( c == this->last_1 ) && ( c == this->last_2 ) && ( c == this->last_3 ) ) {
            count = 0;
            while ( count < 255 && ( ++iterador < (texto+blockLength) ) ) {
				c = *iterador;
                if ( c == last_1 )
                    count++;
                else
                    break;
            }
            
            *compressed += (char) count;
            
            if( count != 255 && c >= 0 )
                *compressed += (char) count;
        }
		
		iterador++;
	}
}

#endif /* RLE_H_ */
